package cn.elead.chaos.sso.server.web.login.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.eventbus.AsyncEventBus;

import cn.elead.chaos.framework.web.global.ApiAssert;
import cn.elead.chaos.framework.web.global.ErrorCodeEnum;
import cn.elead.chaos.framework.web.global.response.UnifiedReturn;
import cn.elead.chaos.mybatils.web.controller.BaseController;
import cn.elead.chaos.sso.core.user.LoginUser;
import cn.elead.chaos.sso.server.web.login.helper.SsoWebLoginHelper;
import cn.elead.chaos.sso.server.web.login.service.RedisSaveService;
import cn.elead.chaos.sso.server.web.login.vo.PV;
import cn.elead.chaos.sso.server.web.system.domain.SsoClient;
import cn.elead.chaos.sso.server.web.system.mapper.SsoClientMapper;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;

@RestController
@RequestMapping("redis")
public class RedisController extends BaseController {

	@Autowired
	private RedisSaveService redisSaveService;

	@Autowired
	private SsoWebLoginHelper ssoWebLoginHelper;

	@Autowired
	private SsoClientMapper clientMapper;

	@Autowired
	private AsyncEventBus eventBus;

	@UnifiedReturn
	@GetMapping("/token/{code}")
	public String codeToToekn(@PathVariable("code") String code, @RequestHeader("clientId") String clientId, @RequestHeader("clientSecret") String clientSecret) {
		// 校验code是否正确
		ApiAssert.equals(ErrorCodeEnum.BAD_REQUEST.convert("code不正确"), code, HexUtil.encodeHexStr(SecureUtil.md5(clientSecret)));
		// 校验客户端
		vaild(clientId, clientSecret);

		// 通过code获取token
		String token = redisSaveService.getCode(code);
		ApiAssert.notNull(ErrorCodeEnum.UNAUTHORIZED.convert("code失效,请重新登录"), token);
		return token;
	}

	@UnifiedReturn
	@GetMapping("/user/{token}")
	public LoginUser getUser(@PathVariable("token") String token, @RequestHeader("clientId") String clientId, @RequestHeader("clientSecret") String clientSecret) {
		// 校验客户端
		vaild(clientId, clientSecret);

		LoginUser loginUser = redisSaveService.getLoginUser(token);
		ApiAssert.notNull(ErrorCodeEnum.UNAUTHORIZED.convert("token失效,请重新登录"), loginUser);
		return loginUser;
	}

	@UnifiedReturn
	@DeleteMapping("/logout/{token}")
	public void logout(@PathVariable("token") String token, @RequestHeader("clientId") String clientId, @RequestHeader("clientSecret") String clientSecret) {
		// 校验客户端
		vaild(clientId, clientSecret);
		ssoWebLoginHelper.logout(request, response, token);
	}

	@UnifiedReturn
	@PutMapping("/pv/{token}")
	public void pv(@PathVariable("token") String token, @RequestHeader("clientId") String clientId, @RequestHeader("clientSecret") String clientSecret) {
		// 校验客户端
		// vaild(clientId, clientSecret);
		PV pv = new PV(token, clientId, clientSecret);
		eventBus.post(pv);
	}

	/**
	 * 校验客户端
	 * 
	 * @param code
	 * @param clientId
	 * @param clientSecret
	 */
	private void vaild(String clientId, String clientSecret) {
		// 客户端Id没有配置
		ApiAssert.notNull(ErrorCodeEnum.BAD_REQUEST.convert("客户端Id没有配置"), clientId);
		// 客户点秘钥不能为空
		ApiAssert.notNull(ErrorCodeEnum.BAD_REQUEST.convert("客户端秘钥没有配置"), clientSecret);

		SsoClient ssoClient = redisSaveService.getClient(clientId);
		if (ObjectUtil.isEmpty(ssoClient)) {
			ssoClient = clientMapper.selectSsoClientById(clientId);
			ApiAssert.notNull(ErrorCodeEnum.BAD_REQUEST.convert("您好,客户端ID不正确,请先注册单点客户端信息!"), ssoClient);
			redisSaveService.saveClientToRedis(clientId, ssoClient);
		}
		// 校验clientSecret是否正确
		ApiAssert.equals(ErrorCodeEnum.BAD_REQUEST.convert("客户端秘钥错误!"), clientSecret, ssoClient.getClientSecret());
	}

}
